package com.yazi.mxz.gather.main.goods;

import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;


import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.util.EntityUtils;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.yazi.mxz.gather.common.App;
import com.yazi.mxz.gather.common.App.PicObject;
import com.yazi.mxz.gather.entity.enums.ProcessType;
import com.yazi.mxz.gather.entity.http.LifufoodResBody;
import com.yazi.mxz.gather.entity.http.LifufoodResBody4Cat;
import com.yazi.mxz.gather.entity.http.LifufoodResBody4Detail;
import com.yazi.mxz.gather.entity.http.LifufoodResBody.Td;
import com.yazi.mxz.gather.entity.http.LifufoodResBody.Tr;
import com.yazi.mxz.gather.entity.http.LifufoodResBody4Cat.Span;
import com.yazi.mxz.gather.entity.repository.ProcessLog;
import com.yazi.mxz.gather.entity.repository.Product;
import com.yazi.mxz.gather.repository.ProcessLogRepository;
import com.yazi.mxz.gather.repository.ProductRepository;

/**
 * 利福食品
 * http://lifufood.com
 * @author mo_yq5
 * @date 2015-8-9
 */
public class LifufoodCom extends Thread {
	
	CloseableHttpAsyncClient httpclient;
	ProcessLogRepository logRepository;
	ProductRepository productRepository;
	ObjectMapper om;
	
	public LifufoodCom() {
		init();
	}
	

	public LifufoodCom(int startPage, int endPage) {
		init();
		ProcessLog log = logRepository.findOne(ProcessType.LIFUFOOD.ordinal());
		if (null == log) {
			log = new ProcessLog();
			log.setId(ProcessType.LIFUFOOD.ordinal());
			log.setCur((long)startPage);
			log.setEnd((long)endPage);
			log.setCount(0);
			logRepository.insert(log);
		} else {
			log.setCur((long)startPage);
			log.setEnd((long)endPage);
			logRepository.save(log);
		}
	}
	
	public void init() {
		
		productRepository = App.context.getBean(ProductRepository.class);
		logRepository = App.context.getBean(ProcessLogRepository.class);
		
		httpclient = HttpAsyncClients.createDefault();
		httpclient.start();
		
		om = new XmlMapper();
		om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
	}


	@Override
	public void run() {
		
		ProcessLog log = logRepository.findOne(ProcessType.LIFUFOOD.ordinal());
		if (null == log) {
			System.out.println(ProcessType.LIFUFOOD + "日志不存在");
			return;
		}
		
		boolean isContinue = false;
		
		try {
			
			while (true) {
				
				if (log.getCur() > log.getEnd()) {
					isContinue = false;
					break;
				}
				
				barcodeInfo(log.getCur());
				
				log.setCur(log.getCur() + 1);
				logRepository.save(log);
			
				sleep(200);
			}
			
		} catch (SocketException e) {
			e.printStackTrace();
			isContinue = true;
			
		} catch (Exception e1) {
			e1.printStackTrace();
			
		} 
		if (isContinue) {
			run();
		} else {
			System.out.println("执行结束！");
		}
	}
	
	private String barcodeInfo(long pageNum) throws JsonParseException, JsonMappingException,
			IOException, InterruptedException, ExecutionException {
		
		System.out.println("PageNum:" + pageNum);
		
		final HttpGet req = new HttpGet("http://lifufood.com/?gallery---0--" + pageNum + "--grid.html");
		Future<HttpResponse> future = httpclient.execute(req, null);
		HttpResponse res = future.get();
		
		System.out.println(req.getRequestLine() + "->" + res.getStatusLine());
		
		String body = EntityUtils.toString(res.getEntity(), "utf-8");
		if (body.isEmpty()) {
			System.out.println("无响应内容!");
			return null;
		}
		
		//<table width="100%" border="0" cellpadding="0" cellspacing="0" class='grid'> <tbody>
		//</tbody> </table> <script>
		int startIndex = body.indexOf("<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" class='grid'> <tbody>");
		int endIndex = body.indexOf("</table> <script>") + 8;
		body = body.substring(startIndex, endIndex);
		
		// 修改正源标签错误
		body = body.replaceAll("</li>  </li>", "</li>")// 标签起止标签不匹配
				.replaceAll("</tr>  </tr>", "</tr>") // 标签起止标签不匹配
				.replaceAll("title=\"查看详细\"", "") // 一个标签中重复相同属性
				.replaceAll("<td colspan=\"3\">&nbsp;</td>", "");
		
		//System.out.println(body);
		
		LifufoodResBody lifufood = om.readValue(body, LifufoodResBody.class);
		List<Tr> trs = lifufood.getTbody().getTrs();
		StringBuffer goodsInfo = new StringBuffer();
		String proId, name, barcode, pic, price, catName, brandName, unit, detailUrl, bigPic, mkPrice;
		for (Tr tr : trs) {
			List<Td> tds = tr.getTds(); // 每行中的商品td
			
			for (Td td : tds) {
				goodsInfo = new StringBuffer();
				proId = td.getProduct();// (站点)商品ID
				detailUrl = td.getDiv().getDivs().get(0).getA().getHref();// 商品详情地址
				name = td.getDiv().getDivs().get(0).getA().getImg().getAlt().trim();// 商品名称(包含条码)
				pic = td.getDiv().getDivs().get(0).getA().getImg().getSrc();// 商品小图片路径(完整路径)
				if (pic.equals("http://lifufood.com/images/default/default_thumbnail_pic.gif")) {
					pic = null;
				} 
				price = td.getDiv().getDivs().get(1).getTable().getTrs().get(1).getTds().get(0).getUl().getLis().get(0).getSpan().getValue().trim();// 单价(如 ￥99.99)
				price = price.replace("￥", "");
				bigPic = td.getDiv().getDivs().get(1).getTable().getTrs().get(2).getTds().get(1).getUl().getLis().get(2).getA().getPic();// // 商品大图片路径(完整路径)
				if (bigPic.equals("http://lifufood.com/images/default/default_thumbnail_pic.gif")) {
					bigPic = null;
				} 
				mkPrice = td.getDiv().getDivs().get(1).getTable().getTrs().get(2).getTds().get(0).getSpan().getValue();// 市场价(如 ￥99.99)
				
				if (name.length() >= 13) {
					barcode = name.substring(name.length() - 13);
				} else {
					System.out.println("商品无条码: " + proId + " -> " + name);
					continue;
				}
		
				if (!App.checkBarCode(barcode)) {
					System.out.println("商品无条码: " + proId + " -> " + name);
					continue;
				}
				
				name = name.replaceAll("\\*,", "")
						.replaceAll("\\*，", "")
						.replaceAll(",", "")
						.replaceAll("，", "")// 去掉名称与条码连接符号
						.replaceAll(barcode, "");	
					
				Map<String, String> detail = getDetailInfo(detailUrl);
				catName = detail.get("catName");
				brandName = detail.get("brandName");
				unit = detail.get("unit");
				
				goodsInfo.append("\r\nID:" + proId);
				goodsInfo.append("\r\n名称:" + name);
				goodsInfo.append("\r\n单位:" + unit);
				goodsInfo.append("\r\n单价:" + price);
				goodsInfo.append("\r\n市场价:" + mkPrice);
				goodsInfo.append("\r\n分类:" + catName);
				goodsInfo.append("\r\n品牌:" + brandName);
				goodsInfo.append("\r\n小图:" + pic);
				goodsInfo.append("\r\n大图:" + bigPic);
				goodsInfo.append("\r\n地址:" + detailUrl);
				System.out.println(goodsInfo);
				
				App.PicObject picObj = new App.PicObject();
				
				if (null != pic ) {
					App.setPic(pic, picObj);
				}
				if (null != bigPic) {
					App.setPic(bigPic, picObj);
				}
				
				if (!productRepository.exists(barcode)) {
					
					System.out.println("添加: " + barcode + " -> " + name);
					
					Product product = new Product();

					//product.setArea(items.getCountry());
					product.setBarcode(barcode);
					product.setBigPic(App.saveGoodsBigImageV1(picObj.getBigPic()));
					product.setBrandName(brandName);
					product.setCatName(catName);
					//product.setFacCode(items.getFacCode());
					//product.setFacName(items.getFacName());
					product.setIsCheckName(true);
					product.setMidPic(App.saveGoodsMiddleImageV1(picObj.getMidPic()));
					product.setName(name);
					//product.setSpell(rs.getString("pinyin"));
					product.setPic(App.saveGoodsImageV1(picObj.getPic()));
					product.setPrice(price);
					product.setUnit(unit);
					product.setSource("lifufood.com");
					//product.setSpec(items.getSpec());
					//product.setSupplier(items.getSupplier());
					product.setSysRemark(proId);

					productRepository.insert(product);

				} else {
					
					System.out.println("修改: " + barcode + " -> " + name);

					Product product = productRepository.findOne(barcode);

					if (null == product.getBigPic()) {
						product.setBigPic(App.saveGoodsBigImageV1(picObj.getBigPic()));
					}
					if (null == product.getMidPic()) {
						product.setMidPic(App.saveGoodsMiddleImageV1(picObj.getMidPic()));
					}
					if (null == product.getPic()) {
						product.setPic(App.saveGoodsImageV1(picObj.getPic()));
					}
					
					if (null != brandName && null == product.getBrandName()) {
						product.setBrandName(brandName);
					}
					if (null != catName && null == product.getCatName()) {
						product.setCatName(catName);
					}
					if (null != name && null == product.getName()) {
						product.setName(name);
					}
					if (null != price && null == product.getPrice()) {
						product.setPrice(price);
					}
					if (null != unit && null == product.getUnit()) {
						product.setUnit(unit);
					}
					
					productRepository.save(product);

				}
			}
			
		}
		
		return null;
	}
	
	private Map<String, String> getDetailInfo(String url) throws InterruptedException, ExecutionException, ParseException, IOException {

		final HttpGet req = new HttpGet(url);
		Future<HttpResponse> future = httpclient.execute(req, null);
		HttpResponse res = future.get();
		
		System.out.println(req.getRequestLine() + "->" + res.getStatusLine());
		
		StringBuffer bodySb = new StringBuffer(EntityUtils.toString(res.getEntity(), "utf-8"));
		if (bodySb.length() == 0) {
			System.out.println("无响应内容!");
			return null;
		}
		String str;
		// 分类相关
		int start = bodySb.indexOf("<div class=\"Navigation\">");
		int end = bodySb.indexOf(" </div> <div class=\"mainColumn pageMain\">");
		String catStr = bodySb.substring(start, end);
		catStr =  catStr.replace("<span>&raquo;</span></td>", "");
				//.replaceAll("您当前的位置： ", "");
		
		LifufoodResBody4Cat lifufood4Cat = om.readValue(catStr, LifufoodResBody4Cat.class);
		List<Span> spans = lifufood4Cat.getSpans();
		spans.remove(0);// 删除"首页"
		String catName = "";
		for (Span span : spans) {
			catName += (catName.isEmpty() ? "":",") +  span.getA().getText();// 各级分类间用,号
		}
		
		// 其它详情
		
		// <li><span>计量单位：</span>盒</li> 改成 <li><span>计量单位：</span><a>盒</a></li>
		str = "<span>计量单位：</span>";
		if ( (start = bodySb.indexOf(str)) > -1) {
			start = start + str.length();
			bodySb.insert(start, "<a>");
			end = bodySb.indexOf("</li>", start);
			bodySb.insert(end, "</a>");
		}
		// <li><span>所得积分：</span><span id="goodsScore">1</span> 末尾加 </li>
		str = "<span>所得积分：</span>";
		if ( (start = bodySb.indexOf(str)) > -1) {
			end = bodySb.indexOf("</ul>", start);
			bodySb.insert(end, "</li>");
		}
		start = bodySb.indexOf("<ul class=\"goodsprops clearfix\">");
		end = bodySb.indexOf("<ul class='goods-price list'>");
		String detailStr =  bodySb.substring(start, end);
				
		//System.out.println(detailStr);
		LifufoodResBody4Detail lifufood4Detail = om.readValue(detailStr, LifufoodResBody4Detail.class);
		String brandName = null; 
		String unit = null;
		try {
			brandName = lifufood4Detail.getLis().get(3).getA().getText();// 品牌 
		} catch (Exception e) {}
		try {
			unit = lifufood4Detail.getLis().get(4).getA().getText();// 单位
		} catch (Exception e) {}
		
		Map<String, String> detail = new HashMap<String, String>();
		
		detail.put("catName", catName);
		detail.put("brandName", brandName);
		detail.put("unit", unit);
		return detail;
	}
	
}
